package edu.usf.imunet.rendering;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

public class BackgroundRenderer {
    private static final String TAG = BackgroundRenderer.class.getSimpleName();

    // components_per_vertex * number_of_vertices * float_size
    private static final int COORDS_BUFFER_SIZE = 2 * 4 * 4;

    private static final FloatBuffer NDC_QUAD_COORDS_BUFFER =
            ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();

    private static final FloatBuffer VIRTUAL_SCENE_TEX_COORDS_BUFFER =
            ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();

    static {
        NDC_QUAD_COORDS_BUFFER.put(
                new float[] {
                        /*0:*/ -1f, -1f, /*1:*/ +1f, -1f, /*2:*/ -1f, +1f, /*3:*/ +1f, +1f,
                });
        VIRTUAL_SCENE_TEX_COORDS_BUFFER.put(
                new float[] {
                        /*0:*/ 0f, 0f, /*1:*/ 1f, 0f, /*2:*/ 0f, 1f, /*3:*/ 1f, 1f,
                });
    }

    private final FloatBuffer cameraTexCoords =
            ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();

    private final Mesh mesh;
    private final VertexBuffer cameraTexCoordsVertexBuffer;
    private final Texture cameraDepthTexture;
    private final Texture cameraColorTexture;

    private boolean useDepthVisualization;
    private boolean useOcclusion;
    private float aspectRatio;

    /**
     * Allocates and initializes OpenGL resources needed by the background renderer. Must be called
     * during a {@link SampleRender.Renderer} callback, typically in {@link
     * SampleRender.Renderer#onSurfaceCreated()}.
     */
    public BackgroundRenderer(MotionRajawaliRenderer render) {
        cameraColorTexture =
                new Texture(
                        render,
                        Texture.Target.TEXTURE_EXTERNAL_OES,
                        Texture.WrapMode.CLAMP_TO_EDGE,
                        /*useMipmaps=*/ false);
        cameraDepthTexture =
                new Texture(
                        render,
                        Texture.Target.TEXTURE_2D,
                        Texture.WrapMode.CLAMP_TO_EDGE,
                        /*useMipmaps=*/ false);

        // Create a Mesh with three vertex buffers: one for the screen coordinates (normalized device
        // coordinates), one for the camera texture coordinates (to be populated with proper data later
        // before drawing), and one for the virtual scene texture coordinates (unit texture quad)
        VertexBuffer screenCoordsVertexBuffer =
                new VertexBuffer(render, /* numberOfEntriesPerVertex=*/ 2, NDC_QUAD_COORDS_BUFFER);
        cameraTexCoordsVertexBuffer =
                new VertexBuffer(render, /*numberOfEntriesPerVertex=*/ 2, /*entries=*/ null);
        VertexBuffer virtualSceneTexCoordsVertexBuffer =
                new VertexBuffer(render, /* numberOfEntriesPerVertex=*/ 2, VIRTUAL_SCENE_TEX_COORDS_BUFFER);
        VertexBuffer[] vertexBuffers = {
                screenCoordsVertexBuffer, cameraTexCoordsVertexBuffer, virtualSceneTexCoordsVertexBuffer,
        };
        mesh =
                new Mesh(render, Mesh.PrimitiveMode.TRIANGLE_STRIP, /*indexBuffer=*/ null, vertexBuffers);
    }








    /** Return the camera color texture generated by this object. */
    public Texture getCameraColorTexture() {
        return cameraColorTexture;
    }

    /** Return the camera depth texture generated by this object. */
    public Texture getCameraDepthTexture() {
        return cameraDepthTexture;
    }
}

